package com.gitee.kamismile.stone.rpc.core.invocation;

import com.gitee.kamismile.stone.commmon.base.ResultVO;
import com.gitee.kamismile.stone.rpc.api.invocation.support.StoneInvocation;
import com.gitee.kamismile.stone.rpc.api.invocation.support.StoneInvocationContextCompletableFuture;
import com.gitee.kamismile.stone.rpc.api.invocation.support.StoneInvocationFactory;
import com.gitee.kamismile.stone.rpc.api.invocation.support.StoneInvokerUtils;
import com.gitee.kamismile.stone.rpc.common.invocation.StoneInvocationType;
import com.gitee.kamismile.stone.rpc.common.dto.StoneAppResponse;
import com.gitee.kamismile.stone.rpc.api.engine.StoneAppEngine;
import com.gitee.kamismile.stone.rpc.common.support.StoneURL;
import com.gitee.kamismile.stone.rpc.core.proxy.IStoneProxy;
import java.util.Objects;
import  org.slf4j.LoggerFactory;
import org.slf4j.Logger;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.CompletableFuture;

public class StoneInvokeInvoker<T> {

    protected static final Logger logger = LoggerFactory.getLogger(StoneInvokeInvoker.class);


    private Class<T> mapperInterface;

    private String serverName;

    private String serverVersion;

    private int timeout;

    private StoneURL stoneURL;

    private StoneAppEngine stoneAppEngine;


    public StoneInvokeInvoker(Class<T> mapperInterface, String serverName, String serverVersion, StoneURL stoneURL, int timeout, StoneAppEngine stoneAppEngine) {
        this.mapperInterface = mapperInterface;
        this.serverName = serverName;
        this.serverVersion = serverVersion;
        this.timeout = timeout;
        this.stoneAppEngine = stoneAppEngine;
        this.stoneURL = stoneURL;
    }


    public Class<T> getMapperInterface() {
        return mapperInterface;
    }

    public String getServerName() {
        return serverName;
    }

    public String getServerVersion() {
        return serverVersion;
    }

    public int getTimeout() {
        return timeout;
    }

    public StoneURL getStoneURL() {
        return stoneURL;
    }

    public StoneAppEngine getStoneAppEngine() {
        return stoneAppEngine;
    }


    public CompletableFuture<Object> completableFutureInvoke(StoneInvocation invocation) {
        CompletableFuture<Object> future = new StoneInvocationContextCompletableFuture<Object>(invocation);
        StoneInvokerUtils.reactiveInvoke(invocation, response -> {
//            if (!response.isSuccess()) {
//                logger.error("{} not found or timeout ", invocation.getServerAddress());
//                ResultVO resultVO = new ResultVO();
//                resultVO.setSuccess(false);
//                resultVO.setCode(ErrorEnum.NOSERVICEORTIMEOUT.getCode() + "");
//                resultVO.setMessage(ErrorEnum.NOSERVICEORTIMEOUT.getMessage());
//                response.setResultVO(resultVO);
//            }

           if(!Objects.isNull(response.getException())){
               future.completeExceptionally(response.getException());
           } else{
               Object result = response.getData();
               future.complete(result);
           }
        });
        return future;
    }

    public Object syncInvoke(StoneInvocation invocation) throws Throwable {
        StoneAppResponse response = StoneInvokerUtils.innerSyncInvoke(invocation);
        if (response.getSuccess()) {
            return response.getData();
        }
        throw response.getException();
    }

    public void checkValid() {
        this.stoneAppEngine.ensureStatusUp();
    }
}
